/*
* Matthew Parker
* CPE 301
* Assignment 2
* 3/3/2014
*
* Designed for the ATmega328P and made in AtmelStudio 6.1
* 
* This program will...
* 1. Use a delay subroutine to generate a waveform with a 50% DC and 0.5 sec period
* 2. Use an 8-bit counter that counts on every falling edge of that waveform
* 3. Every 10th falling edge of the counter will toggle an output bit
* 4. That output bit will be connected to INT0 and will call a subroutine every falling edge as an interrupt
*    The interrupt will toggle a different output bit every 2nd time it is called
*/

#include <avr/io.h>
#include <avr/interrupt.h>

void delay(void);

int main(void)
{
	//SP = RAMEND; //Initiate the stack
	DDRB = 0xFF; //Set all of port B, and C as outputs
	DDRC = 0xFF;
	DDRD = 0x00; //Set all of port D as input
	PORTC = 0x01;  //PC0 will be used as the waveform with a 0.5 period and 50% DC
				   //PC1 will be toggled every 10th falling edge
				   //PC2 will be an exact copy of PC1
				   //PC3 will be toggled every 2nd time INT0 has a falling edge
	TCNT0 = 0x00;  //8-bit counter that increases on waveform's falling edge
	PORTB = 0x00;  //output of the 8-bit counter
	EIMSK = 0x01; //Enable INT0 (PD2) as interrupt pin
	EICRA = 0x02; //Trigger interrupt on falling edge
	sei(); //Enable interrupts
	while(1){
		delay();
		PORTC ^= 0x01; //Toggle PC0
		if ((PORTC&0x01) == 0x00){
			//if PC0 is 0, then 8-bit Counter++
			TCNT0++;
		}
		PORTB = TCNT0;
		if ((TCNT0 % 10) == 0){
			//Every 10th falling edge, toggle PC1 and PC2
			//PC2 is a copy of PC1 in order to have enough voltage to go to an LED and INT0
			PORTC ^= 0x06;
		}
	}
	return 0;
}
void delay(void){
	//this function will use timer1 to make a 0.25 second delay
	//Possible shortcut for this function: _delay_ms(2500);
	//TCNT = 2^16 - (0.25 sec at 8 MHz)/Prescalar
	//2^16 - 2*10^6/Prescalar > 0
	//Prescalar > 2*10^6 / 2^16 = 30
	//TCNT = 2^16 - 2*10^6 / 64 = 34286 = 0x85EE
	TCCR1A = 0x00;
	TCCR1B = 0x03; //Normal Mode, CS code of 011 for prescalar 64
	TCNT1 = 0x85EE;
	while ((TIFR1&0x01) == 0x00){
		//wait
	}
	TIFR1 = 0x01; //Clear the overflow flag by setting it to 1
}

ISR (INT0_vect){
	//This will be called every falling edge of INT0
	//INT0 should be connected to PC2
	TCNT2++; //The value of the first bit (TCNT2) will change every 2nd call to this function
	PORTC += 3<<TCNT2; //PC3 will be the output, and PC7:4 will get filled with junk
	PORTC &= 0x0F;     //Get rid of the junk while preserving PC3:0
}
